package com.gisfinal.core;

import java.util.concurrent.ConcurrentHashMap;

import com.lambkit.common.service.ServiceObject;
import com.lambkit.core.aop.AopKit;
import com.lambkit.core.config.ConfigManager;
import com.lambkit.core.rpc.RpcConfig;
import com.lambkit.core.rpc.RpcKit;

public class GISFinal {

	private static final GISFinal me = new GISFinal();
	
	public static GISFinal me() {
		return me;
	}
	
	private ConcurrentHashMap<String, ServiceObject> services;
    
    public ConcurrentHashMap<String, ServiceObject> getServices() {
    	if(services==null) {
    		services = new ConcurrentHashMap<>();
    	}
    	return services;
    }
    
    public void put(String name, ServiceObject service) {
    	getServices().put(service.getInterfaceClass().getName() + ":" + name, service);
    }
   
    /**
     * server端或者本地自用的接口服务注册
     * @param interfaceClass
     * @param implementClass
     * @param mockClass
     */
    public void mapping(String name, Class<?> interfaceClass, Class<?> implementClass, Class<?> mockClass) {
    	RpcConfig rpcConfig = ConfigManager.me().get(RpcConfig.class);
    	mapping(name, interfaceClass, implementClass, mockClass, rpcConfig.getDefaultGroup(), rpcConfig.getDefaultVersion(), rpcConfig.getDefaultPort());
    }
    
    /**
     * server端或者本地自用的接口服务注册
     * @param interfaceClass
     * @param implementClass
     * @param mockClass
     * @param group
     * @param version
     * @param port
     * @return
     */
    public boolean mapping(String name, Class<?> interfaceClass, Class<?> implementClass, Class<?> mockClass, String group, String version, int port) {
    	ServiceObject service = new ServiceObject(interfaceClass, implementClass, mockClass, group, version, port);
    	put(name, service);
    	if(implementClass!=null && implementClass!=interfaceClass) {
    		return RpcKit.serviceExport(interfaceClass, service.inject(), group, version, port);
    	}
    	return false;
	}
    
    /**
     * rpc中client端的接口服务注册
     * @param interfaceClass
     * @param mockClass
     */
    public void remote(String name, Class<?> interfaceClass, Class<?> mockClass) {
    	RpcConfig rpcConfig = ConfigManager.me().get(RpcConfig.class);
    	ServiceObject service = new ServiceObject(interfaceClass, null, mockClass, rpcConfig.getDefaultGroup(), rpcConfig.getDefaultVersion(), rpcConfig.getDefaultPort());
    	service.setType(ServiceObject.CLIENT);
    	put(name, service);
	}
    
    /**
     * rpc中client端的接口服务注册
     * @param interfaceClass
     * @param mockClass
     * @param group
     * @param version
     * @param port
     */
    public void remote(String name, Class<?> interfaceClass, Class<?> mockClass, String group, String version, int port) {
    	ServiceObject service = new ServiceObject(interfaceClass, null, mockClass, group, version, port);
    	service.setType(ServiceObject.CLIENT);
    	put(name, service);
	}
    
    /**
     * 获取服务接口
     * @param interfaceClass
     * @return
     */
    public <T> T instance(String name, String interfaceClassName) {
    	ServiceObject service = getServices().get(interfaceClassName + ":" + name);
    	if(service!=null) {
    		return service.instance();
    	}
    	return null;
    }
    
    /**
     * 获取服务接口
     * @param interfaceClass
     * @return
     */
    public <T> T inject(String name, String interfaceClassName) {
    	ServiceObject service = getServices().get(interfaceClassName + ":" + name);
    	if(service!=null) {
    		return service.inject();
    	}
    	return null;
    }
    /**
     * 获取服务接口
     * @param interfaceClass
     * @return
     */
    public <T> T inject(String name, Class<?> interfaceClass) {
    	ServiceObject service = getServices().get(interfaceClass.getName() + ":" + name);
    	if(service!=null) {
    		return service.inject();
    	}
    	return null;
    }
    /**
     * 获取服务接口
     * @param interfaceClass
     * @param defaultClass
     * @return
     */
    public <T> T inject(String name, Class<?> interfaceClass, Class<?> defaultClass) {
    	ServiceObject service = getServices().get(interfaceClass.getName() + ":" + name);
    	if(service!=null) {
    		return service.inject();
    	} else {
    		return (T) AopKit.singleton(defaultClass);
    	}
    }
}
